package com.tianhe.common.tongsuo;

import org.apache.ibatis.executor.resultset.ResultSetHandler;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Signature;
import org.springframework.beans.factory.annotation.Autowired;

import java.lang.reflect.Field;
import java.sql.Statement;
import java.util.List;

import static org.springframework.util.ClassUtils.isPrimitiveOrWrapper;

@Intercepts({
        @Signature(type = ResultSetHandler.class, method = "handleResultSets", args = {Statement.class})
})
public class DecryptoInterceptor implements Interceptor {

    @Autowired
    private SM4JNI sm4JNI;

    private static final String DEFAULT_SM4_KEY = "0123456789ABCDEF";
    private static final String DEFAULT_SM4_IV = "iv1234567890abc!";

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        Object result = invocation.proceed();

        if (result instanceof List) {
            ((List<?>) result).forEach(this::processDecryption);
        } else {
            processDecryption(result);
        }

        return result;
    }

    private void processDecryption(Object obj) {
        if (obj == null || isPrimitiveOrWrapper(obj.getClass())) return;

        for (Field field : obj.getClass().getDeclaredFields()) {
            if (field.isAnnotationPresent(Tongsuo.class)) {
                try {
                    field.setAccessible(true);
                    Object value = field.get(obj);
                    if (value instanceof String) {
                        field.set(obj, decryptField((String) value, field.getAnnotation(Tongsuo.class)));
                    }
                } catch (IllegalAccessException e) {
                    throw new RuntimeException("字段解密失败: " + field.getName(), e);
                }
            }
        }
    }

    private String decryptField(String value, Tongsuo crypto) {
        if (value == null) return null;

        switch (crypto.algorithm()) {
            case SM4_CBC:
                return sm4JNI.cbcDecrypt(DEFAULT_SM4_IV, value);
            case SM4_ECB:
                return value;
            case SM3: // SM3不可逆，直接返回原值
            default:
                return value;
        }
    }
}
